#!/bin/bash

#****************************************************************#
# ScriptName: quick-start.sh
# Author: xiebaoyou@kernelsoft.com
#	  wuhengxing@kernelsoft.com
# Create Date: 2023-01-28 13:25
# Function: 常用脚本功能集合，使用方法:
#		执行默认功能，编译并运行kernel
#			bash quick-start.sh
#		以bash quick-start.sh + 函数名的方式，调用执行某个子功能，例如：
#			bash quick-start.sh devel	编译准备
#		注意：可以向函数传递参数，例如：
#			bash quick-start.sh check init/main.c
#***************************************************************#

PWD="`pwd`"

#
# 如果使用其他版本的交叉编译工具链，请在这里替换正确的工具链版本路径
# 或者使用环境变量的方式，正确设置CROSS_COMPILE环境变量
#
if [ -z $CROSS_COMPILE ];then
	CROSS_COMPILE=aarch64-linux-gnu-
fi

#
# 调用checkpatch.pl检查代码格式，例如：
#    bash quick-start.sh check init/main.c
#
function check()
{
	./scripts/checkpatch.pl -f --no-tree $*
}

function distclean()
{
	echo "====>distclean"
	make distclean
	make ARCH=arm64 clean
	echo "====>distclean 完成"
}

function defconfig()
{
	make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE defconfig
}

function menuconfig()
{
	make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE menuconfig
}

#
# 开发准备工作，第一次运行一下即可
#
function devel()
{
	distclean
	defconfig
}

function run()
{
	echo "====>通过qemu运行"
	qemu-system-aarch64 -nographic \
	  -machine virt,gic-version=3 \
	  -cpu cortex-a53 -smp 4 -m 2G \
	  -append "root=/dev/ram0" \
	  -initrd ./build/rootfs.img \
	  -kernel ./arch/arm64/boot/Image
}

function image()
{
	make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE -j8 Image modules
}

#
# 默认执行此函数
# 注意：make和run之间用&&连接
# 这样编译错误的时候，不会运行
# 避免控制台中的编译错误被冲掉
#
function all()
{
	echo "====>make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE -j8 Image modules"
	make ARCH=arm64 CROSS_COMPILE=$CROSS_COMPILE -j8 Image modules && run && exit
}

function usage()
{
	echo "请使用合适的参数"
	echo "使用方法:"
	echo "  执行默认功能，编译并运行kernel"
	echo "      bash quick-start.sh"
	echo "  以 bash quick-start.sh + 函数名的方式，调用执行某个子功能，例如："
	echo "      bash quick-start.sh devel	编译准备"
	echo "注意：可以向函数传递参数，例如："
	echo "  bash quick-start.sh check init/main.c"
}

#
# 将字符串转换为函数，并调用函数
#
function call_sub_cmd()
{
	#
	# 通过第一个参数，获得想要调用的函数名
	# 例如 check 函数
	#
	func=$1
	#
	# 函数名不支持”-“，因此将参数中的”-“转换为”_“
	#
	func=${func//-/_}
	#
	# 从参数列表中移除第一个参数，例如 check，将剩余的参数传给函数
	#
	shift 1
	eval "$func $*"
}

#
# 主函数
#
function main()
{
	#
	# 如果没有任何参数，默认调用all函数
	#
	if [ $# -eq 0 ]; then
		all
		exit 0
	fi

	#
	# 带参数运行，看看相应的函数是否存在
	#
	SUB_CMD=$1
	type ${SUB_CMD//-/_} > /dev/null 2>&1
	#
	# 要调用的子函数不存在，说明用法错误
	#
	if [ $? -ne 0 ]; then
		usage
		exit
	else
		#
		# 要调用的子函数存在，执行子函数
		#
		shift 1;
		call_sub_cmd $SUB_CMD $*
		exit $?
	fi

	usage
}

#
# 调用主函数
#
main $*
